package com.inspectortime.webapp.err;

import java.util.Date;
import java.util.Enumeration;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.RandomStringUtils;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.log4j.NDC;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;

public class ExceptionResolver implements HandlerExceptionResolver {

	private Log log = LogFactory.getLog(ExceptionResolver.class);
	
	private String errorView;
	private boolean live;
	
	public String getErrorView() {
		return errorView;
	}

	public boolean isLive() {
		return live;
	}

	public void setLive(boolean live) {
		this.live = live;
	}

	public void setErrorView(String errorView) {
		this.errorView = errorView;
	}

	public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object source,
			Exception exception) {
		
		String reference = RandomStringUtils.randomAlphanumeric(10).toUpperCase();
		
		NDC.push("RemoteAddress: " + request.getRemoteAddr() + "\n"
				+ "RequestURL: " + request.getRequestURL() + "\n"
				+ "QueryString: " + request.getQueryString() + "\n"
				+ "Parameters: " + printParameters(request) + "\n"
				+ "Cookies: " + printCookies(request) + "\n"
				//+ "Headers: " + printHeaders(request) + "\n"
			);
		log.error("Exception reference: " + reference, exception);
		NDC.pop();
		NDC.remove();
		
		ModelAndView mv = new ModelAndView(errorView);
		mv.addObject("logExceptionTime", new Date());
		mv.addObject("logExceptionID", reference);
		if (!live) {
			String stack = ExceptionUtils.getFullStackTrace(exception).replaceAll("\n", "<br>");			
			mv.addObject("logException", stack);	
			mv.addObject("logExceptionMessage", exception.getMessage());
		}		
		
		return mv;
	}
	
	private String printParameters(HttpServletRequest request) {
		StringBuilder sb = new StringBuilder();
		Enumeration<String> parameterNames = request.getParameterNames();
		while (parameterNames.hasMoreElements()) {
			String name = parameterNames.nextElement(); 
			if (!name.contains("password")){
				sb.append(name + "=" + request.getParameter(name) + "|");	
			}
		}
		return sb.toString();
	}

	private String printCookies(HttpServletRequest request) {
		StringBuilder sb = new StringBuilder();
		if (request.getCookies() != null) {
			for (Cookie cookie : request.getCookies()) {
				sb.append(cookie.getName() + "=" + cookie.getValue() + "|");
			}			
		} else {
			sb.append("NO COOKIES FOUND");
		}
		return sb.toString();
	}

	private String printHeaders(HttpServletRequest request) {
		StringBuilder sb = new StringBuilder();
		Enumeration<String> headerNames = request.getHeaderNames();
		while (headerNames.hasMoreElements()) {
			String name = headerNames.nextElement(); 
			sb.append(name + "=" + request.getHeader(name) + "|");
		}
		return sb.toString();
	}
	
}
